<?php

/**
 * class for administrating accounts and assign permissions to users
 *
 * @author Wouter Bakker
 */
class Administrator {

	private static $instance = null;
	private $database;
	private $config;

	private function __construct() {
		$this->database = Database::getInstance();
		$this->config = Config::getInstance();
	}

	private function __clone() {
		//enforece singleton
	}

	public static function getInstance() {
		return is_object(self::$instance) ? self::$instance : (self::$instance = new self() );
	}

	/**
	 * Add a new user to the db
	 * @param string $name name
	 * @param string $surname surname
	 * @param string $email email
	 * @param int $active active
	 * @return array $succes Succes, id, name
	 */
	public function addUser($name, $surname, $email, $active, $password) {
		$q = "INSERT INTO user_accounts
									(name, surname, email, active, password)
									VALUES ('" . $name . "', '" . $surname . "', '" . $email . "', $active, '" . md5($password) . "')";
		$r = $this->database->dbQuery($q);
		$id = $this->database->dbLastInsertId();
		$succes = $r ? true : false;
		return array('succes' => $succes, 'id' => $id, 'name' => $name, 'surname' => $surname);
	}

	/**
	 * Delete a user from the db
	 * @param int $id
	 * @return void
	 */
	public function deleteUser($id) {
		$r = $this->database->dbQuery("DELETE FROM user_accounts
										WHERE id=$id
										LIMIT 1");
		$s = $this->database->dbQuery("DELETE FROM user_assign
										WHERE uid=$id");
		$succes = ($r || $s) ? true : false;
		return array('succes' => $succes);
	}

	/**
	 * Returns details of one user
	 * @param int $id userId
	 * @return array $r Array of user details
	 */
	public function userDetails($id) {
		$r = $this->database->dbRow("SELECT * FROM user_accounts WHERE id = $id");
		return $r;
	}

	/**
	 * Save user details
	 * @param string $name name
	 * @param string $surname surname
	 * @param string $email email
	 * @param int $active active
	 * @return array $succes Succes, id, name
	 */
	public function saveUserDetails($id, $name, $surname, $email, $active, $password) {
		$result = $this->database->dbRow("SELECT * FROM user_accounts
						WHERE id = $id
						AND password = '" . md5($password) . "' "
		);
		if ($result == true || $password == '') {
			//password didn't change, or no password provided
			$q = "UPDATE user_accounts
						SET name = '" . $name . "', surname = '" . $surname . "', email = '" . $email . "', active = $active 
						WHERE id = $id
						LIMIT 1";
			$r = $this->database->dbQuery($q);
			$succes = $r ? true : false;
			return array('succes' => $succes);
		} else {
			//password changed
			$q = "UPDATE user_accounts
					SET name = '" . $name . "', surname = '" . $surname . "', email = '" . $email . "', active = $active, password = '" . md5($password) . "' 
					WHERE id = $id
					LIMIT 1";
			$r = $this->database->dbQuery($q);
			$succes = $r ? true : false;
			return array('succes' => $succes);
		}
	}

	/**
	 * Return array with all known users
	 * @param void
	 * @return array $r Array of all users
	 */
	public function listUsers() {
		$r = $this->database->dbAll("SELECT * FROM user_accounts ORDER by name");
		return $r;
	}

	/**
	 * Return array of set of roles assigned to a user
	 * @param int $id User id
	 * @return array $r All roles assigned to user
	 */
	public function assignedRoles($id) {
		$r = $this->database->dbAll("SELECT r.id, r.name 
										FROM user_accounts u INNER JOIN user_assign ua
										ON u.id = ua.uid
										INNER JOIN roles r
										ON ua.rid = r.id
										WHERE u.id = $id");
		return $r;
	}

	/**
	 * Return set of all roles
	 * @param void
	 * @return array $r All roles
	 */
	public function listRoles() {
		$r = $this->database->dbAll("SELECT * FROM roles");
		return $r;
	}

	/**
	 * Return set of users assigned to a role
	 * @param int $id Role id
	 * @return array $r All users assigned to role
	 */
	public function assignedUsers($id) {
		$r = $this->database->dbAll("SELECT u.id, u.name , u.surname
										FROM user_accounts u INNER JOIN user_assign ua
										ON ua.uid = u.id
										WHERE ua.rid = $id");
		return $r;
	}

	/**
	 * Return set of users not assigned to a role
	 * @param int $id Role id
	 * @return array $r All users not assigned to role
	 */
	public function deassignedUsers($id) {
		$r = $this->database->dbAll("SELECT a.id, a.name, a.surname
										FROM user_accounts a
										LEFT OUTER JOIN
										(
											SELECT ua.uid
											FROM user_assign ua
											INNER JOIN user_accounts u
											ON ua.uid = u.id
											WHERE ua.rid = $id
										) b
										ON b.uid = a.id
										WHERE uid IS NULL");
		return $r;
	}

	/**
	 * Assign a role to a user
	 * @param int $uid User id
	 * @param int $rid Role id
	 * @return bool $succes 
	 */
	public function assignUser($uid, $rid) {
		$r = $this->database->dbQuery("INSERT INTO user_assign
									(uid, rid)
									VALUES ($uid, $rid)");
		$succes = $r ? true : false;
		return array('succes' => $succes);
	}

	/**
	 * deassign a role from a user
	 * @param int $uid User id
	 * @param int $rid Role id
	 * @return bool $succes 
	 */
	public function deassignUser($uid, $rid) {
		$r = $this->database->dbQuery("DELETE FROM user_assign
										WHERE uid = $uid
										AND rid = $rid");
		$succes = $r ? true : false;
		return array('succes' => $succes);
	}

	/**
	 * Return set of permissions granted to a role
	 * @param int $id Role id
	 * @return array $r All permissions granted to role
	 */
	public function assignedPermissions($id) {
		$r = $this->database->dbAll("SELECT p.id, p.name, p.plugin
										FROM permissions p INNER JOIN permission_assign pa
										ON p.id = pa.pid
										WHERE pa.rid = $id
										ORDER BY p.plugin, p.name");
		return $r;
	}

	/**
	 * Return set of permissions not assigned to a role
	 * @param int $id Role id
	 * @return array $r All permissions not assigned to role
	 */
	public function deassignedPermissions($id) {
		$r = $this->database->dbAll("SELECT a.id, a.name, a.plugin
										FROM permissions a
										LEFT OUTER JOIN 
										(
										SELECT pa.pid 
										FROM permission_assign pa
										INNER JOIN permissions p
										ON pa.pid = p.id
										WHERE pa.rid = $id
										) b
										ON a.id = b.pid
										WHERE pid IS NULL
										ORDER BY a.plugin, a.name");
		return $r;
	}

	/**
	 *	Return all assigned permissions to a user
	 * @param int $id	User id
	 * @return array $r All permissions assignd to a user 
	 */	
	public function userAssignedPermissions($id) {
		$r = $this->database->dbAll("SELECT p.name, p.plugin
										FROM user_accounts u INNER JOIN user_assign ua
										ON u.id = ua.uid
										INNER JOIN permission_assign pa
										ON ua.rid = pa.rid
										INNER JOIN permissions p
										ON pa.pid = p.id
										WHERE u.id = $id
										GROUP BY p.id
										ORDER BY p.plugin");
		return $r;
	}

	/**
	 * Grant permission to a role
	 * @param int $pid Permission id
	 * @param int $rid Role id
	 * @return bool $succes 
	 */
	public function grantPermission($pid, $rid) {
		$r = $this->database->dbQuery("INSERT INTO permission_assign
									(rid, pid)
									VALUES ($rid, $pid)");
		$succes = $r ? true : false;
		return array('succes' => $succes);
	}

	/**
	 * Revoke permission from a role
	 * @param int $pid Permission id
	 * @param int $rid Role id
	 * @return bool $succes 
	 */
	public function revokePermission($pid, $rid) {
		$r = $this->database->dbQuery("DELETE FROM permission_assign
										WHERE pid = $pid
										AND rid = $rid");
		$succes = $r ? true : false;
		return array('succes' => $succes);
	}

	/**
	 * Add a new role
	 * @param string $name
	 * @return array $r succes, name, id
	 */
	public function addRole($name) {
		$q = "INSERT INTO roles (id, name)
			VALUES (NULL, '" . $name . "')";
		$r = $this->database->dbQuery($q);
		$id = $this->database->dbLastInsertId();
		$succes = $r ? true : false;
		return array('succes' => $succes, 'id' => $id, 'name' => $name);
	}

	/**
	 * Edit a role
	 * @param int $id Role id
	 * @param string $name Name
	 * @return array $r succes
	 */
	public function editRole($id, $name) {
		$q = "UPDATE roles
				SET name = '" . $name . "'
				WHERE id = $id
				LIMIT 1";
		$r = $this->database->dbQuery($q);
		$succes = $r ? true : false;
		return array('succes' => $succes);
	}

	/**
	 * Delete a role and all of his assigned permissions
	 * @param int $id Role id
	 * @return bool $succes
	 */
	public function deleteRole($id) {
		$r = $this->database->dbQuery("DELETE FROM roles
										WHERE id=$id
										LIMIT 1");
		$s = $this->database->dbQuery("DELETE FROM user_assign
										WHERE rid=$id");
		$t = $this->database->dbQuery("DELETE FROM permission_assign
										WHERE rid=$id");
		$succes = ($r || $s || $t) ? true : false;
		return array('succes' => $succes);
	}

}

?>
